﻿
-----------------------------------------------------------------------
-- MatrixCommon.lua
--
-- A Framework for World Of Warcraft addons
-- Copyright (C) 2007  wwkkii
-- 
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- any later version.
-- 
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
-- 
-- You should have received a copy of the GNU General Public License
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
-- 
-- Home Page: http://code.google.com/p/wowmatrix
-----------------------------------------------------------------------

local __version__ = { "MatrixCommon", 0, 1, 1 };
if (MatrixUpdateVersion(__version__)) then return; end

-----------------------------------------------------------------------
-- Variables
-----------------------------------------------------------------------

MatrixCommon = { };

-----------------------------------------------------------------------
-- Local functions
-----------------------------------------------------------------------

local function Matrix_SuperInitial(obj, ...)
	local class;

	class = rawget(obj, "__class__");
	rawset(obj, "__class__", class.__super__);
	class.__super__.Initial(obj, ...);
	rawset(obj, "__class__", class);
end

local function Matrix_DeleteObject(obj, class)
	while (type(class) == "table") do
		rawset(obj, "__class__", class)
		class.Final(obj);
		class = rawget(class, "__super__");
	end
	setmetatable(obj, nil);
	if (obj.__var__ and (_G[obj.__var__] == obj)) then
		_G[obj.__var__] = nil;
	end
	obj.__var__ = nil;
	obj.__class__ = nil;
	obj.__deleted__ = true;
end

-------------------------------------------------------------------------------
-- Matrix Common
-------------------------------------------------------------------------------

-- For Class/Interface
function MatrixCommon:Static(name, val)
end

-- For Class/Interface
function MatrixCommon:Const(name, val)
end

-- For Class/Interface
function MatrixCommon:Variant(name, val)
end

-- Only For Class
function MatrixCommon:Initial(...)
	self:Super(...)
end

-- Only For Class
function MatrixCommon:Final()
end

-- Only For Class
function MatrixCommon:New(...)
	local obj, result, mesg, errval;

	if (self.__mode__ == MATRIX_VIRTUAL_CLASS) then
		matrix.Crash("ERROR_NEW_VIRTUAL", self.__name__);
	end

	obj = { };
	obj.__class__ = self;
	obj.Super = Matrix_SuperInitial;
	setmetatable(obj, self);
	result, mesg = pcall(self.Initial, obj, ...);
	if (result) then
		rawset(obj, "Super", nil);
		rawset(obj, "__class__", nil);
		if (obj.__var__ and (_G[obj.__var__] == nil)) then
			_G[obj.__var__] = obj;
		end
		return obj;
	end
	errval = matrix.GetException(mesg);
	pcall(Matrix_DeleteObject, obj, rawget(obj, "__class__"));
	matrix.__error__ = errval;
	error(mesg, 0);
end

-- Only For Class
function MatrixCommon:FromHandle(id, ...)
	return nil;
end

function MatrixCommon:Delete()
	if (rawget(self, "Final")) then
		rawset(self, "__class__", self);
		self:Final();
	end
	Matrix_DeleteObject(self, getmetatable(self));
end

function MatrixCommon:Name()
	return self.__name__;
end

function MatrixCommon:Handle()
	return self.__handle__;
end

function MatrixCommon:Print(mesg, ...)
	matrix.Print(mesg, ...);
end

function MatrixCommon:GetUUID()
	local mt, val;

	mt = getmetatable(self);
	setmetatable(self, nil);
	val = string.match(tostring(self), "table:.%s*(%x+)");
	setmetatable(self, mt);
	return "0x"..tostring(val);
end

function MatrixCommon:Class()
	return getmetatable(self);
end

function MatrixCommon:Match(class)
	local node;

	node = getmetatable(self);
	while (node ~= nil) do
		if (node == class) then
			return true;
		end
		node = rawget(node, "__super__");
	end
	return false;
end

function MatrixCommon:Crash(mesg, ...)
	mesg = tostring(self).."/Crash: "..matrix.TextInfo(mesg, ...);
	matrix.Cout(1, 0, 0, mesg);
	matrix.Throw(mesg, self, 3);
end

function MatrixCommon:Error(mesg, ...)
	mesg = tostring(self).."/Error: "..matrix.TextInfo(mesg, ...);
	matrix.Cout(1, 0, 0, mesg);
	if (matrix.IsErrorStop()) then
		matrix.Throw(mesg, self, 3);
	end
end

function MatrixCommon:Warning(mesg, ...)
	mesg = tostring(self).."/Warning: "..matrix.TextInfo(mesg, ...);
	matrix.Cout(0, 1, 1, mesg);
	if (matrix.IsWarningStop()) then
		matrix.Throw(mesg, self, 3);
	end
end

function MatrixCommon:Invoke(func, ...)
	if (type(func) == "string") then
		func = self[func];
	end
	return matrix.Invoke(func, self, ...);
end

function MatrixCommon:SafeInvoke(func, ...)
	if (type(func) == "string") then
		func = self[func];
	end
	return matrix.SafeInvoke(func, self, ...);
end
